/**
 * https://github.com/AndreLion/expirable-localstorage
 */
(function(S, ls) {
  if (!ls) {
    return true;
  }
  let EXP_DATA = '_EXPIRES_DATA_';
  let EXP_LAST_CHECK = '_EXPIRES_LAST_CHECK_';
  S.prototype._setItem = S.prototype.setItem;
  let delimiter1st = 'ˆ';
  let delimiter2nd = '☈';
  let now = +new Date;
  let ms = {
    s: 1000,
    min: 60000,
    h: 3600000, // 60*60*1000
    d: 86400000, // 24*60*60*1000
    week: 604800000, // 7*24*60*60*1000
    mon: 2592000000, // 30*24*60*60*1000
    year: 31536000000 // 365*24*60*60*1000
  };
  const decode = function(str) {
    str = str || '';
    let result = {};
    let arr = str.split(delimiter1st);
    let kv = [];
    for (let i = 0, l = arr.length; i < l; i++) {
      if (arr[i] !== '') {
        kv = arr[i].split(delimiter2nd);
        result[kv[0]] = kv[1];
      }
    }
    return result;
  };
  const encode = function(obj) {
    let result = [];
    for (let p in obj) {
      if (obj.hasOwnProperty(p)) {
        let value = obj[p];
        if (typeof(value) === 'string') {
          result.push(p + delimiter2nd + value);
        }
      }
    }
    return result.join(delimiter1st);
  };
  const check = function() {
    let expires = decode(ls.getItem(EXP_DATA));
    let newExpires = {};
    let removedData;
    for (let p in expires) {
      if (expires.hasOwnProperty(p)) {
        if (expires[p] < now) {
          removedData = ls.getItem(p);
          ls.removeItem(p);
          console.log('[Expired! Removed!]' + p + ' : ' + removedData);
        } else {
          newExpires[p] = expires[p];
        }
      }
    }
    for (let i = 0, l = ls.len; i < l; i++) {
      let key = ls.key(i);
      if (key !== EXP_DATA || key !== EXP_LAST_CHECK) {
        if (!newExpires[key]) {
          newExpires[key] = now + ms.mon;
        }
      }
    }
    ls._setItem(EXP_LAST_CHECK, now);
    ls._setItem(EXP_DATA, encode(newExpires));
  };
  S.prototype.setItem = function(k, v, conf) {
    conf = conf || {};
    let exp = conf.expires;
    if (exp && exp instanceof Date && exp.getTime() > now) {
      // valid  Date arguments
    } else if (/^\d{1,5}(s|min|h|d|week|mon|year)$/.test(exp)) {
      let num = +exp.match(/\d+/)[0];
      let unit = exp.match(/s|min|h|d|week|mon|year/)[0];
      // valid shortcut arguments
      let delta = num * ms[unit];
      exp = new Date((+new Date) + delta);
    } else {
      console.log('Invalid expire data argument.');
      exp = new Date();
      exp.setTime(now + ms.mon);
    }
    let expires = decode(ls.getItem(EXP_DATA));
    expires[k] = exp.getTime() + '';
    this._setItem(EXP_DATA, encode(expires));
    return this._setItem.apply(this, arguments);
  };
  let lastCheckTime = +ls.getItem(EXP_LAST_CHECK);
  if (1 || now - lastCheckTime > ms.day) {
    check();
  }
})(window.Storage, window.localStorage);
